package App.Service;

import App.Entity.*;
import App.Repository.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.util.JSONPObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.jca.cci.CciOperationNotSupportedException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import App.Utils.PoJo.*;

import javax.management.ObjectName;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

import static App.Conflict.Constant.Finish;
import static App.Conflict.Constant.Running;

/**
 * Created by yu on 2017/7/19.
 */
@Service
@Transactional
public class PersonService {
    @Autowired
    PersonRepository personRepository;
    @Autowired
    TaskCheckRepository taskCheckRepository;
    @Autowired
    TaskRepository taskRepository;
    @Autowired
    ProjectRepository projectRepository;
    @Autowired
    ProjectCheckRepository projectCheckRepository;
    @Autowired
    NoticeRepository noticeRepository;
    @Autowired
    NoticeCheckRepository noticeCheckRepository;
    @Autowired
    ContactCheckRepository contactCheckRepository;
    //简单缓存
    //public static ConcurrentHashMap<Long,Map<String,Object>> noticeCache=new ConcurrentHashMap<>();

    //更新用户详情
    public void updatePerson(Person person)
    {
        Person p=personRepository.findFirstByAuthId(person.getAuthId());
        if(person.getCellphone()!=null) {
            p.setCellphone(person.getCellphone());
        }
        if(person.getDescription()!=null){
            p.setDescription(person.getDescription());
        }
        if(person.getLocation()!=null)
        {
            p.setLocation(person.getLocation());
        }
        if(person.getUsername()!=null){
            p.setUsername(person.getUsername());
        }
        if(person.getImg()!=null){
            p.setImg(person.getImg());
        }
        personRepository.save(p);
    }

    //获取某个用户的详情
    public Person getPerson(Long auth_id)
    {
        Person person=personRepository.findFirstByAuthId(auth_id);
        return person;
    }

    //更新头像路径
    public void updateImg(long authId,String imgUrl)
    {
        Person person=personRepository.findFirstByAuthId(authId);
        String oldImg=person.getImg();
        //删除旧的头像
        File f=new File(oldImg);
        if(f.isFile()){
            f.delete();
        }
        person.setImg(imgUrl);
        personRepository.save(person);
        //personRepository.updateImgByAuthId(imgUrl,authId);
    }

    //获取图像路径
    public String getPersonImgByAuthId(long auth_id)
    {
        return personRepository.getPersonImgByAuthId(auth_id);
    }

    //获得正在进行中的任务
    public List<Map<String,Object>> getRunningTasks(Long AuthId)
    {
        List<Task> tasks=(List<Task>) taskRepository.findAll(taskCheckRepository.getRunningTaskByAuthId(AuthId));
        return tasks.stream().map((item)->{
            Map<String,Object>resItem=item.toMap();
            resItem.put("projectName",(projectRepository.getProjectName(item.getProjectId())));
            return resItem;
        }).collect(Collectors.toList());
    }

    //分页获取已经完成的任务，默认一页10条数据
    public List<Map<String,Object>> getFinishTasksByPages(Long AuthId,int page)
    {
        List<Long> ids=taskCheckRepository.getFinishedTaskByAuthId(AuthId,new PageRequest(page,10));
        List<Task> tasks=(List<Task>) taskRepository.findAll(ids);
        return tasks.stream().map((item)->{
            Map<String,Object>resItem=item.toMap();
            resItem.put("projectName",(projectRepository.getProjectName(item.getProjectId())));
            return resItem;
        }).collect(Collectors.toList());
    }

    //根据身份Id和项目状态获得项目
    private List<Project> getProjects(Long AuthId,int status){
        List<Long>ids=projectCheckRepository.getProjectIdsByAuthId(AuthId);
        List<Project> res=new ArrayList<>();
        if(ids.size()>0){
            res=projectRepository.findAllByIdsAndStatusOrderByPublicTimeDesc(ids,status);
            res.sort((o1, o2) -> {
                if(o1.getPublicTime()<o2.getPublicTime()) return 1;
                else if(o1.getPublicTime()==o2.getPublicTime()) return 0;
                return -1;
            });
        }
        return res;
    }

    //获取正在进行的项目
    public List<Project> getRunningProjects(Long AuthId)
    {
        return this.getProjects(AuthId,Running);
    }

    //获取已经完成的项目
    public List<Project> getFinishedProjects(Long AuthId){
        return this.getProjects(AuthId,Finish);
    }

    //获得所有未读的通知
    public List<Map<String,Object>> getUnReadNotice(Long AuthId){
        List<Long>ids=noticeCheckRepository.findNoticeIdByAuthIdAndStatus(AuthId,0);//获取所有未读通知的ID
        List<Notice> notices=(List<Notice>) noticeRepository.findAll(ids);
        return handleNotices(notices);
    }

    //分页获得已读的通知，
    public List<Map<String,Object>> getReadNotice(Long AuthId,int page){
        List<Long>ids=noticeCheckRepository.findNoticeIdByAuthIdAndStatus(AuthId,1,new PageRequest(page,10, Sort.Direction.DESC,"publicTime"));
        List<Notice> notices=(List<Notice>) noticeRepository.findAll(ids);
        return handleNotices(notices);
    }

    //获得新的通知,用于更新
    public List<Map<String,Object>> getNewNotice(Long AuthId,Long time){
        return noticeCheckRepository.findAllByReceiverIdAndPublicTimeGreaterThanOrderByPublicTimeDesc(AuthId,time).
                stream().map(check->{
                    Notice notice=noticeRepository.findOne(check.getNoticeId());
                    if(notice==null) return null;
                    Map<String,Object>res=notice.toMap();
                    String projectName="unknown";
                    String publisherName="unknown";
                    if(notice.getProjectId()!=null){
                        projectName=projectRepository.getProjectName(notice.getProjectId());
                    }
                    if(notice.getPublisher()!=null) {
                        publisherName = personRepository.getPersonNameByAuthId(notice.getPublisher());
                    }
                    res.put("projectName",projectName);
                    res.put("publisherName",publisherName);
                    String publishTime=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(notice.getPublicTime()));
                    res.put("publishTime",publishTime);
                    res.put("publishTimeStamp",notice.getPublicTime());
                    res.put("status",check.getStatus());
                    return res;
        }).collect(Collectors.toList());
    }

    //处理notice信息
    private List<Map<String,Object>> handleNotices(List<Notice> notices){
        return notices.stream().map(notice -> {
            Map<String,Object>noticeMap=notice.toMap();
            String projectName="unknown";
            String publisherName="unknown";
            if(notice.getProjectId()!=null){
                projectName=projectRepository.getProjectName(notice.getProjectId());
            }
            if(notice.getPublisher()!=null) {
                publisherName = personRepository.getPersonNameByAuthId(notice.getPublisher());
            }
            noticeMap.put("projectName",projectName);
            noticeMap.put("publisherName",publisherName);
            String publishTime=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(notice.getPublicTime()));
            noticeMap.put("publishTime",publishTime);
            noticeMap.put("publishTimeStamp",notice.getPublicTime());
            return noticeMap;
        }).collect(Collectors.toList());
    }

    //标记该通知已读
    public void readNotice(Long AuthId,Long NoticeId){
        NoticeCheck check=noticeCheckRepository.findByReceiverIdAndNoticeId(AuthId,NoticeId);
        if(check!=null){
            check.setRead();
        }
        noticeCheckRepository.save(check);
    }

    //获取所有联系人信息
    public List<Person> getContacts(Long authId){
        List<ContactCheck> contactChecks=contactCheckRepository.findContactChecksByOwnerIdOrderByAddTimeDesc(authId);
        if(contactChecks.size()==0) return null;
        return contactChecks.stream().filter(check->check.getContactId()!=null).map(check->{
            Person person=personRepository.findFirstByAuthId(check.getContactId());
            return person;
        }).filter(Objects::nonNull).collect(Collectors.toList());
    }

    //判断是否存在联系人
    public boolean existContact(Long authId,Long contactId){
        if(Objects.equals(authId, contactId)) return true;
        return contactCheckRepository.findContactCheckByOwnerIdAndContactId(authId, contactId)!=null;
    }

    //添加联系人
    public void addContacts(Long authId,Long contactId){
        ContactCheck check=new ContactCheck();
        check.setAddTime(System.currentTimeMillis());
        check.setContactId(contactId);
        check.setOwnerId(authId);
        contactCheckRepository.save(check);
        ContactCheck check2=new ContactCheck();
        check2.setAddTime(System.currentTimeMillis());
        check2.setContactId(authId);
        check2.setOwnerId(contactId);
        contactCheckRepository.save(check2);
    }

    //确认是否同意邀请成为好友
    public JsonObject comfirmInvite(Long noticeId,boolean confirm){
        JsonObject res=new JsonObject();
        Notice notice=noticeRepository.findOne(noticeId);
        if(notice==null){
            res.put("error","不存在邀请");
            return res;
        }
        //确认该条信息已读
        NoticeCheck check = noticeCheckRepository.findFirstByNoticeId(noticeId);
        check.setRead();
        noticeCheckRepository.save(check);
        //确认联系人
        Long authId=notice.getPublisher();
        Long contactId=notice.getReceiver();
        Person contact=personRepository.findFirstByAuthId(contactId);
        if(contact==null){
            res.put("error","不存在该人");
            return res;
        }
        //发信回复邀请者
        Notice reply=new Notice();
        reply.setTitle("加友验证");
        if(confirm){
            //如果确认的话即添加好友
            addContacts(authId,contactId);
            reply.setDescription(contact.getUsername()+"已通过你的好友邀请");
        }
        else{
            reply.setDescription(contact.getUsername()+"拒绝了你的好友邀请");
        }
        //回复
        sendNotice(contactId,authId,reply);
        res.put("success","确认成功");
        return res;
    }

    public void inviteFriend(Long authId, Long contactId, String mark){
        Person inviter=getPerson(authId);
        if(inviter==null) return;
        String authName=inviter.getUsername();        //邀请人的名称
        Notice notice=new Notice();
        notice.setTitle(authName+" 想添加你为好友");
        notice.setDescription(mark);
        notice.setType(Notice.FRIEND_INVITE);
        notice.setPublicTime(System.currentTimeMillis());
        notice.setProjectId(-1L);
        notice.setPublisher(authId);                //publisher即是我们的邀请人
        notice.setReceiver(contactId);
        sendNotice(authId,contactId,notice);
    }


    //点对点发送通知
    public JsonObject sendNotice(Long sender,Long receiver,Notice notice){
        notice.setPublisher(sender);
        notice.setReceiver(receiver);
        noticeRepository.save(notice);
        NoticeCheck check=new NoticeCheck();
        check.setProjectId(-1L);
        check.setReceiverId(receiver);
        check.setStatus(NoticeCheck.NotRead);
        check.setPublicTime(notice.getPublicTime());
        check.setNoticeId(notice.getId());
        noticeCheckRepository.save(check);
        JsonObject json=new JsonObject();
        json.put("check",check);
        json.put("notice",notice);
        return json;
    }




    //query为搜索语句，索引为username
    //返回搜索结果
    public List<Person> findContacts(String query){
        return personRepository.findByUsernameLike(query);
    }

    //query为搜索语句，索引为cellphone
    //返回搜索结果
    public List<Person> findContactsLikeCellPhone(String query){
        return personRepository.findByCellphoneLike(query);
    }









}
